package dataStore;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dataStruct.ChunkInfo;
import dataStruct.FileInfo;
import dataStruct.WordcountFileInfo;

public class FtpServerApi implements FtpServerApiInterface {
	public FtpServerApi(Map<String, FileInfo> fileMd5FileContentMap,
			Map<String, WordcountFileInfo> wordcountFileMd5Map) {
		FtpServerApi.fileMd5FileContentMap = fileMd5FileContentMap;
		FtpServerApi.wordcountFileMd5Map = wordcountFileMd5Map;
		FtpServerApi.fileMd5FileContentMap.clear();
	}

	@Override
	public Boolean upload_chunk(ChunkInfo chunkInfo, String ftpFilePath,
			Long totalSize) {
		// debug
		System.out.println(String.format("uploading chunk(FtpServerApi.java)"));
		if ((chunkInfo.chunkContent != null)
				&& (chunkInfo.chunkWordcountMap == null)) {
			if (fileMd5FileContentMap.containsKey(ftpFilePath) == false) {
				FileInfo fileInfo = new FileInfo();
				fileInfo.totalSize = totalSize;
				fileInfo.fileContent = new byte[totalSize.intValue()];
				fileMd5FileContentMap.put(ftpFilePath, fileInfo);
			}
			FileInfo fileInfo = fileMd5FileContentMap.get(ftpFilePath);
			fileInfo.totalSize -= chunkInfo.size;
			System.arraycopy(chunkInfo.chunkContent, 0, fileInfo.fileContent,
					chunkInfo.offset.intValue(), chunkInfo.size.intValue());

			System.out
					.println(String
							.format("chunkContent=%s, lenth = %d, offset = %d, size = %d , ftpFilePath = %s has finished upload(FtpServerApi.java)",
									chunkInfo.chunkContent.toString(),
									chunkInfo.chunkContent.length,
									chunkInfo.offset, chunkInfo.size,
									ftpFilePath));

			// debug
			System.out
					.println(String
							.format("after upload a chunk, the remain total size = %d(FtpServerApi.java)",
									fileInfo.totalSize));
			System.out.println(String.format(
					"fileContent = %s, lenth = %d(FtpServerApi.java)",
					fileInfo.fileContent.toString(),
					fileInfo.fileContent.length));

			if (fileInfo.totalSize <= 0) {
				// debug
				System.out
						.println(String
								.format("slavers finished upload all chunk(FtpServerApi.java)"));
				System.out.println(String.format(
						"fileContent = %s, lenth = %d(FtpServerApi.java)",
						fileInfo.fileContent.toString(),
						fileInfo.fileContent.length));
				File file = new File(ftpFilePath);
				try {
					if (!file.exists()) {
						file.createNewFile();
					}
					FileOutputStream out = new FileOutputStream(file);
					out.write(fileInfo.fileContent);
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return false;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return false;
				}
			}
		} else if ((chunkInfo.chunkContent == null)
				&& (chunkInfo.chunkWordcountMap != null)) {

			if (wordcountFileMd5Map.containsKey(ftpFilePath) == false) {
				WordcountFileInfo wordcountFileInfo = new WordcountFileInfo();
				wordcountFileInfo.wordcountMap = new HashMap<String, Integer>();
				wordcountFileInfo.totalSize = totalSize;
				wordcountFileMd5Map.put(ftpFilePath, wordcountFileInfo);
			}
			WordcountFileInfo wordcountFileInfo = wordcountFileMd5Map
					.get(ftpFilePath);
			wordcountFileInfo.totalSize -= chunkInfo.size;
			Integer count;
			for (Map.Entry<String, Integer> e : chunkInfo.chunkWordcountMap
					.entrySet()) {
				if ((count = wordcountFileInfo.wordcountMap.get(e.getKey())) == null) {
					count = 0;
				}
				count += e.getValue();
				wordcountFileInfo.wordcountMap.put(e.getKey(), count);
			}

			// debug
			System.out
					.println(String
							.format("after upload a chunk, the remain total size = %d(FtpServerApi.java)",
									wordcountFileInfo.totalSize));

			if (wordcountFileInfo.totalSize <= 0) {
				File file = new File(ftpFilePath);
				try {
					if (!file.exists()) {
						file.createNewFile();
					}
					FileOutputStream out = new FileOutputStream(file);

					// 通过ArrayList构造函数把map.entrySet()转换成list
					List<Map.Entry<String, Integer>> mappingList = new ArrayList<Map.Entry<String, Integer>>(
							wordcountFileInfo.wordcountMap.entrySet());
					// 通过比较器实现比较排序
					Collections.sort(mappingList,
							new Comparator<Map.Entry<String, Integer>>() {
								public int compare(
										Map.Entry<String, Integer> mapping1,
										Map.Entry<String, Integer> mapping2) {
									return mapping2.getValue() - mapping1.getValue();
									}
							}
					);
					
					for(Map.Entry<String, Integer> mapping:mappingList)
					{
						out.write(String.format("%s %d\n", mapping.getKey(), mapping.getValue()) .getBytes());
					}
					out.close();
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return false;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return false;
				}
			}
		} else {
			System.out.println(String
					.format("Erro: uploading a erro chunk(FtpServerApi.java)"));
		}

		return true;
	}

	private static Map<String, FileInfo> fileMd5FileContentMap;
	private static Map<String, WordcountFileInfo> wordcountFileMd5Map;
}
